package cn.qy.java.base.ch11;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.Clock;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.Random;
import java.util.TimeZone;

public class DateMain {
	
	public static void main(String[] args) {
		Random r = new Random(1);
		System.out.println(r.nextInt());
		r = new Random(1);
		System.out.println(r.nextInt());
		r = new Random(1);
		System.out.println(r.nextInt());
				
		Date date = new Date();
		System.out.println(date);
		
		// Locale 表示国家和语言
		Locale locale = Locale.getDefault();
		System.out.println(locale);
		
		// TimeZone 表示时区
		TimeZone timeZone = TimeZone.getDefault();
		System.out.println(timeZone);
		// 常用时区
		System.out.println(TimeZone.getTimeZone("UTC"));
		System.out.println(TimeZone.getTimeZone("GMT+8"));
		System.out.println(TimeZone.getTimeZone("GMT+8:00"));
		System.out.println(TimeZone.getTimeZone("Zulu"));
		// 遍历所有可用时区的 ID
		System.out.println(Arrays.toString(TimeZone.getAvailableIDs()));
		
		// Calendar 表示日历，在中国一般是格林尼治公历
		Calendar calendar = Calendar.getInstance();
		System.out.println(calendar);
		System.out.println(calendar.get(Calendar.YEAR) + "-" + (1 + calendar.get(Calendar.MONTH)) + "-"+ calendar.get(Calendar.DAY_OF_MONTH));
		// Calendar 转 Date
		Date time = calendar.getTime();
		System.out.println(time);
		
		// DateFormat 使用
		System.out.println(DateFormat.getDateInstance().format(date));
		System.out.println(DateFormat.getTimeInstance().format(date));
		System.out.println(DateFormat.getDateTimeInstance().format(date));
		System.out.println(DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(date));
		System.out.println(DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG).format(date));
		System.out.println(DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM).format(date));
		System.out.println(DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(date));
		// 指定 Locale 信息
		System.out.println(DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, Locale.TRADITIONAL_CHINESE).format(date));
		System.out.println(DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, Locale.FRANCE).format(date));
		System.out.println(DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, Locale.GERMAN).format(date));
		System.out.println(DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, Locale.UK).format(date));
		System.out.println(DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, Locale.US).format(date));
		// 使用 SimpleDateFormat
		System.out.println(new SimpleDateFormat("yyy-MM-dd HH:mm:ss SSS").format(date));

		// 不会存在偏移量
        System.out.println("--------Instant--------");
		Instant instant = Instant.now();
		System.out.println(instant);
		System.out.println(instant.toEpochMilli());
		
		// ZoneOffset 是 Java 8 新增的方法，是 ZoneId 的子类
        System.out.println("--------ZoneOffset--------");
		System.out.println(ZoneOffset.getAvailableZoneIds());
		System.out.println(ZoneOffset.of("+8"));
		System.out.println(ZoneOffset.UTC);
		
		
		// LocalDateTime 转 Instant
		LocalDateTime localDateTime = LocalDateTime.now();
		// 将抛掉8小时 -8
		System.out.println(localDateTime.toInstant(ZoneOffset.of("+8")));
		System.out.println(localDateTime.toInstant(ZoneOffset.UTC));
		System.out.println("------LocalDateTime 通过 of 进行构建-----");
        System.out.println(LocalDateTime.of(2022, 1, 2, 3, 4,5, 666));
        // 北京当地时间 通过传入 ZoneId
        System.out.println(LocalDateTime.now(ZoneId.of("GMT+8")));
        // 北京当地时间 通过传入 ZoneOffset 进行构建
        System.out.println(LocalDateTime.now(ZoneOffset.of("+8")));
		
		// 给定一个时刻，使用不同时区解读，日历信息是不同的
		// 这里指定北京时区
		ZonedDateTime atZone = Instant.now().atZone(ZoneId.of("GMT+8"));
		System.out.println(atZone);
		System.out.println(Instant.now().atZone(ZoneId.of("Z")));
		
		// ZonedDateTime表示特定时区的日期和时间，获取系统默认时区的当前日期和时间
		// 构建：通过 now 进行构建
		System.out.println(ZonedDateTime.now());
		// 构建：使用 Instant 构建 ZonedDateTime
		System.out.println(ZonedDateTime.ofInstant(Instant.now(), ZoneId.systemDefault()));
		// 构建：使用 LocalDateTime 构建 ZonedDateTime， 会结合系统本地的时区
		System.out.println(LocalDateTime.now().atZone(ZoneId.systemDefault()));
		// 转换：ZonedDateTime 转 Instant
		System.out.println(ZonedDateTime.now().toInstant());
		// 转换：ZonedDateTime 转 LocalDateTime 
		System.out.println(ZonedDateTime.now().toLocalDateTime());
		
        // UTC 时钟
        final ZoneId utcZoneId = Clock.systemUTC().getZone();
        // 系统时钟
        final ZoneId defaultZoneId = ZoneId.systemDefault();
        // 上海时钟
        final ZoneId shanghaiZoneId = ZoneId.of("Asia/Shanghai");
        // 东京时钟
        final ZoneId tokyoZoneId = ZoneId.of("Asia/Tokyo");

        System.out.println("--------ZoneId--------");
        System.out.println(utcZoneId);
        System.out.println(defaultZoneId);
        System.out.println(shanghaiZoneId);
        System.out.println(tokyoZoneId);
        
        // 通过 ZoneId 得到 Clock
        System.out.println("--------借助 ZoneId 生成 Clock--------");
        final Clock utcClock = Clock.systemUTC();
        final Clock defaultClock = Clock.systemDefaultZone();
        final Clock shanghaiClock = Clock.system(shanghaiZoneId);
        final Clock tokyoClock = Clock.system(tokyoZoneId);

        System.out.println(utcClock);
        System.out.println(defaultClock);
        System.out.println(shanghaiClock);
        System.out.println(tokyoClock);
        
        // 通过 Clock 拿到 ZoneId
        System.out.println("--------通过 Clock 拿到 ZoneId--------");
        System.out.println(utcClock.getZone());
        System.out.println(defaultClock.getZone());
        System.out.println(shanghaiClock.getZone());
        System.out.println(tokyoClock.getZone());
        
        System.out.println("------通过 now 方法Instant------");
        System.out.println(Instant.now());
        System.out.println(Instant.now(utcClock));
        System.out.println(Instant.now(defaultClock));
        System.out.println(Instant.now(shanghaiClock));
        System.out.println(Instant.now(tokyoClock));
        System.out.println("-------通过 Clock 的快捷方法构建 Instant --");
        System.out.println(utcClock.instant());
        System.out.println(defaultClock.instant());
        System.out.println(shanghaiClock.instant());
        System.out.println(tokyoClock.instant());
        
        System.out.println("------反解析 parse 和 of 及其类似----------");
        // 字符串 反解析为 localDateTime
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
        System.out.println(dateTimeFormatter.getLocale());
        System.out.println(dateTimeFormatter.getZone());
        LocalDateTime ldt = LocalDateTime.parse("2018-06-01 10:12:05", dateTimeFormatter);
        System.out.println("LocalDateTime: " + ldt);
        
        System.out.println("LocalDateTime ISO_DATE_TIME formatter: " + ldt.format(DateTimeFormatter.ISO_DATE_TIME));
        System.out.println("LocalDateTime ISO_LOCAL_DATE_TIME formatter: " + ldt.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        System.out.println("LocalDateTime BASIC_ISO_DATE formatter: " + ldt.format(DateTimeFormatter.BASIC_ISO_DATE));
        System.out.println("LocalDateTime ISO_LOCAL_DATE formatter: " + ldt.format(DateTimeFormatter.ISO_LOCAL_DATE));

        System.out.println("--------test instant2ZonedDateTime--------");
        System.out.println(instant2ZonedDateTime(Instant.now()));
	}
	
    /**
     * Date 2 LocalDateTime
     */
    public static LocalDateTime date2LocalDateTime(final Date date) {
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }

    /**
     * LocalDateTime 2 Date   (该类也是不带时区信息的哦)
     */
    public static Date localDateTime2Date(final LocalDateTime time) {
        // 通过 ZonedDateTime 进行中转
        return Date.from(time.atZone(ZoneId.systemDefault()).toInstant());
    }

	/**
     * LocalDateTime 2 ZonedDateTime
     */
    public static ZonedDateTime localDateTime2ZonedDateTime(final LocalDateTime localDateTime) {
        return localDateTime.atZone(ZoneId.systemDefault());
    }
    
	/**
     * Instant 2 ZonedDateTime
     */
    public static ZonedDateTime instant2ZonedDateTime(final Instant instant) {
        return instant.atZone(ZoneId.systemDefault());
    }

}
